package de.nak.fireDepartment.service;

import java.util.Collection;
import java.util.LinkedList;

import org.apache.log4j.Logger;
import org.springframework.dao.DataIntegrityViolationException;

import de.nak.fireDepartment.dao.EquipmentDAO;
import de.nak.fireDepartment.exceptions.CarNotFoundException;
import de.nak.fireDepartment.exceptions.EquipmentAlreadyExistsException;
import de.nak.fireDepartment.exceptions.EquipmentNotFoundException;
import de.nak.fireDepartment.exceptions.ErrorOnDeleteException;
import de.nak.fireDepartment.logger.MyLog4JLogger;
import de.nak.fireDepartment.model.Car;
import de.nak.fireDepartment.model.Equipment;

/**
 * The equipment service implementation.
 *
 * @author Nils Bredow
 */
public class EquipmentServiceImpl implements EquipmentService {

	private Logger logger;
	
	/**
	 * The Contructor gets the Logger and creates a Message
	 */
	public EquipmentServiceImpl(){
		logger = MyLog4JLogger.getLogger();
		logger.info("Instance of EquipmentServiceImpl has been created");
	}
	
	/**
	 * The room data access object.
	 */
	private EquipmentDAO equipmentDAO;
	
	/**
	 * The carService
	 */
	private CarService carService;
	
	/** {@inheritDoc} */
	public void createEquipment(String modelName,
								String yearOfManufacture,
								String manufactureCompany,
								String descriptionText,
								String imageURL) throws EquipmentAlreadyExistsException, CarNotFoundException {
						
		// Create a new Equipment-Object
		logger.info("Create equipment-Object");
		Equipment equipment = new Equipment();
		// Store values in new Equipment Object
		equipment.setModelName(modelName);
		equipment.setYearOfManufacture(yearOfManufacture);
		equipment.setManufactureCompany(manufactureCompany);
		equipment.setDescriptionText(descriptionText);
		equipment.setImageURL(imageURL);
		
		logger.info("An Equipment has been created");
		try {
			// check for existing Equipment
			checkEquipmentExists(equipment);
			// save Equipment
			equipmentDAO.save(equipment);
			logger.info("An Equipment has been saved");
		}
		catch (DataIntegrityViolationException ex) {
			logger.warn(ex.getStackTrace());
			throw new EquipmentAlreadyExistsException();
		}
	}

	/** {@inheritDoc} */
	public Collection<Equipment> listEquipments() {
		logger.info("A List of Equipment has been requested");
		return equipmentDAO.findAll();
	}

	/** {@inheritDoc} */
	public Equipment showEquipment(Long id) throws EquipmentNotFoundException {
		logger.info("An Equipment should be searched for");
		Equipment equipment = equipmentDAO.findById(id);
		if (equipment == null) {
			logger.warn("Equipment not found");
			throw new EquipmentNotFoundException();
		}
		logger.info("searched Equipment found");
		
		// Convert PersistentCarObjects to CarList
		logger.info("Get cars for the equipment");
		Collection<Car> cars = new LinkedList<Car>();
		for (Car car : equipment.getCars()) {
			cars.add(car);
		}
		equipment.setCars(cars);
		
		return equipment;
	}

	/** {@inheritDoc} */
	public void updateEquipment(long id,
								String modelName,
								String yearOfManufacture,
								String manufactureCompany,
								String descriptionText,
								String imageURL) throws EquipmentNotFoundException, CarNotFoundException, EquipmentAlreadyExistsException {

		
		logger.info("An Equipment has to be updated");
		Equipment equipment = equipmentDAO.findById(id);
		if (equipment == null) {
			logger.warn("Equipment not found");
			throw new EquipmentNotFoundException();
		}
		logger.info("Serached Equipment found");
		
		// check for existing Equipment
		checkEquipmentExists(equipment);
		
		equipment.setModelName(modelName);
		equipment.setYearOfManufacture(yearOfManufacture);
		equipment.setManufactureCompany(manufactureCompany);
		equipment.setDescriptionText(descriptionText);

		if(!imageURL.equals("")){
			equipment.setImageURL(imageURL);
		}
		
		logger.info("Equipment has been updated");
	}

	/** {@inheritDoc} 
	 * @throws ErrorOnDeleteException */
	public void deleteEquipment(Long id) throws EquipmentNotFoundException, ErrorOnDeleteException {
		logger.info("An Equipment should be deleted");
		// get the equipment
		Equipment equipment = equipmentDAO.findById(id);
		if (equipment == null) {
			logger.warn("Equipment not found");
			throw new EquipmentNotFoundException();
		}
		
		// If equipment is linked by cars it can't be deleted
		if(equipment.getCars().size() == 0){
			equipmentDAO.delete(equipment);
			logger.info("Equipment deleted");
		}else{
			logger.info("Equipment can't be deleted due to refertial Integrity");
			throw new ErrorOnDeleteException("text.error.referentialIntegrity.equipment");
		}
	}
	
	/**
	 * Check if a Equipment is alreadyExisting
	 * @param equipment
	 * @throws EquipmentAlreadyExistsException
	 */
	private void checkEquipmentExists(Equipment equipment) throws EquipmentAlreadyExistsException{
		Collection<Equipment> equipments = listEquipments();
		// iterate over all equipments
		for (Equipment equip : equipments) {
			// if modelname == modelname and id != id throw Exception
			if(equipment.getModelName().equals(equip.getModelName()) && equipment.getEquipmentId() != equip.getEquipmentId()){
				logger.info("Equipment already existing");
				throw new EquipmentAlreadyExistsException("text.error.equipmentExists");
			}
		}
	}

	/**
	 * Returns the equipment DAO.
	 * @return the equipmentDAO.
	 */
	public EquipmentDAO getEquipmentDAO() { 
		return equipmentDAO;
	}

	/**
	 * Sets the equipment DAO.
	 * @param equipmentDAO the equipmentDAO to set.
	 */
	public void setEquipmentDAO(EquipmentDAO equipmentDAO) {
		this.equipmentDAO = equipmentDAO;
	}	
	
	/**
	 * Gets the Car Service
	 * @return carService
	 */
	public CarService getCarService() {
		return carService;
	}

	/**
	 * Sets the Car Service
	 * @param carService
	 */
	public void setCarService(CarService carService) {
		this.carService = carService;
	}
}
